home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Technotools
/
Technotools (Chestnut CD-ROM)(1993).ISO
/
lang_oth
/
mawk10
/
jmp.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-10-05
|
6KB
|
235 lines
/********************************************
jmp.c
copyright 1991, Michael D. Brennan
This is a source file for mawk, an implementation of
the AWK programming language.
Mawk is distributed without warranty under the terms of
the GNU General Public License, version 2, 1991.
********************************************/
/* $Log: jmp.c,v $
* Revision 3.3.1.1 91/09/14 17:23:33 brennan
* VERSION 1.0
*
* Revision 3.3 91/08/13 06:51:38 brennan
* VERSION .9994
*
* Revision 3.2 91/06/28 04:16:53 brennan
* VERSION 0.999
*
* Revision 3.1 91/06/07 10:27:42 brennan
* VERSION 0.995
*
* Revision 2.2 91/05/22 07:30:39 brennan
* fixed stack underflow checks to work correctly on large model DOS
*
* Revision 2.1 91/04/08 08:23:19 brennan
* VERSION 0.97
*
*/
/* this module deals with back patching jumps, breaks and continues,
and with save and restoring code when we move code.
There are three stacks. If we encounter a compile error, the
stacks are frozen, i.e., we do not attempt error recovery
on the stacks
*/
#include "mawk.h"
#include "jmp.h"
#include "code.h"
#include "sizes.h"
#include "init.h"
#include "memory.h"
extern unsigned compile_error_count ;
#define error_state (compile_error_count>0)
/* a stack to hold jumps that need to be patched */
#define JMP_STK_SZ (2*MAX_LOOP_DEPTH)
static INST **jmp_stack ;
static INST **jmp_sp ;
/*-------------------------------------*/
/* a stack to hold break or continue that need to be
patched (which is all of them) */
#define BC_SZ MAX_LOOP_DEPTH
/* the stack holds a linked list of these */
struct BC_node { /* struct for the break/continue list */
char type ; /* 'B' or 'C' */
INST *jmp ; /* the jump to patch */
struct BC_node *link ;
} ;
static struct BC_node **BC_stack ;
static struct BC_node **BC_sp ;
/*---------------------------------------*/
/* a stack to hold some pieces of code while
reorganizing loops */
#define LOOP_CODE_SZ (2*MAX_LOOP_DEPTH)
static struct loop_code {
INST *code ;
unsigned len ;
} *loop_code_stack , *lc_sp ;
/*--------------------------------------*/
void jmp_stacks_init()
{ jmp_stack = (INST **) zmalloc(JMP_STK_SZ*sizeof(INST*)) ;
jmp_sp = jmp_stack-1 ;
BC_stack = (struct BC_node **)
zmalloc(BC_SZ*sizeof(struct BC_node*)) ;
BC_sp = BC_stack-1 ;
loop_code_stack = (struct loop_code *)
zmalloc(LOOP_CODE_SZ*sizeof(struct loop_code)) ;
lc_sp = loop_code_stack - 1 ;
}
void jmp_stacks_cleanup()
{ zfree(jmp_stack, JMP_STK_SZ*sizeof(INST*)) ;
zfree(BC_stack, BC_SZ*sizeof(struct BC_node*)) ;
zfree(loop_code_stack, LOOP_CODE_SZ*sizeof(struct loop_code)) ;
}
/*--------------------------------------*/
/* operations on the jmp_stack */
void code_jmp( jtype, target, expr_start)
int jtype ;
INST *target ;
INST *expr_start ; /* used to recognize constant expressions,
which can only be _PUSHC , <address> */
{
if (error_state) return ;
/* check if a constant expression will be at top of stack,
if so replace conditional jump with jump */
if ( jtype != _JMP &&
code_ptr - 2 == expr_start &&
code_ptr[-2].op == _PUSHC )
{ int t = test( (CELL *) code_ptr[-1].ptr ) ;
if ( jtype == _JZ && ! t ||
jtype == _JNZ && t )
{ code_ptr -= 2 ; jtype = _JMP ; }
}
if ( ! target ) /* jump will have to be patched later ,
put it on the jmp_stack */
{ if ( ++jmp_sp == jmp_stack + JMP_STK_SZ )
overflow("jmp stack" , JMP_STK_SZ ) ;
*jmp_sp = code_ptr ;
code2(jtype, 0) ;
}
else
{ INST *source = code_ptr ;
code_ptr++->op = jtype ;
code_ptr++->op = target - source ;
}
}
void patch_jmp(target) /* patch a jump on the jmp_stack */
INST *target ;
{ register INST *source ;
if ( ! error_state )
{
if ( jmp_sp+1 <= jmp_stack ) bozo("jmp stack underflow") ;
source = *jmp_sp-- ;
source[1].op = target - source ;
}
}
/*---------------------------*/
/* a stack of linked lists of BC_nodes for patching
break and continue statements. */
void BC_new() /* push an empty list on the stack */
{
if ( ! error_state )
{ if ( ++BC_sp == BC_stack + BC_SZ ) overflow("BC stack", BC_SZ) ;
* BC_sp = (struct BC_node *) 0 ;
}
}
void BC_insert(type, address)
int type ; INST *address ;
{ register struct BC_node *p ;
if ( error_state ) return ;
if ( BC_sp <= BC_stack - 1 )
{ compile_error( type == 'B' ?
"break statement outside of loop" :
"continue statement outside of loop" ) ;
return ;
}
p = (struct BC_node *) zmalloc( sizeof(struct BC_node) ) ;
p->type = type ; p->jmp = address ;
p->link = *BC_sp ; *BC_sp = p ;
}
void BC_clear(B_address, C_address)
/* patch all break and continues on list */
INST *B_address, *C_address ;
{ register struct BC_node *p , *q ;
if (error_state) return ;
if ( BC_sp+1 <= BC_stack ) bozo("underflow on BC stack") ;
p = *BC_sp-- ;
while ( p )
{ p->jmp[1].op = (p->type=='B' ? B_address : C_address) - p->jmp ;
q = p ; p = p->link ; zfree(q, sizeof(struct BC_node)) ;
}
}
/*---------------------------------------------*/
/* save and restore some code for reorganizing
loops on a stack */
void code_push( p, len)
INST *p ; unsigned len ;
{
if (error_state) return ;
if ( ++lc_sp == loop_code_stack + LOOP_CODE_SZ )
overflow("loop_code_stack" , LOOP_CODE_SZ) ;
if ( len )
{ lc_sp->code = (INST *) zmalloc(sizeof(INST) * len) ;
(void) memcpy(lc_sp->code, p, SIZE_T(sizeof(INST) * len)) ; }
else lc_sp->code = (INST *) 0 ;
lc_sp->len = len ;
}
/* copy the code at the top of the loop code stack to target.
return the number of bytes moved */
unsigned code_pop(target)
INST *target ;
{
if (error_state) return 0 ;
if ( lc_sp+1 <= loop_code_stack ) bozo("loop code stack underflow") ;
if ( lc_sp->len )
{ (void) memcpy(target, lc_sp->code, SIZE_T(lc_sp->len * sizeof(INST))) ;
zfree(lc_sp->code, sizeof(INST)*lc_sp->len) ; }
return lc_sp-- -> len ;
}